package search

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"strconv"

	"github.com/elastic/go-elasticsearch/v9"
	"github.com/elastic/go-elasticsearch/v9/esapi"
	"github.com/samber/do/v2"

	"gitee.com/monkeyPP/happy-mall/pkg/log"
	"gitee.com/monkeyPP/happy-mall/services/productservice/internal/infrastructure/eventbus"
)

const ProductIndexName = "products"

type EsSearchService struct {
	esClient *elasticsearch.Client
}

func NewEsSearchService(i do.Injector) (SearchService, error) {
	client := do.MustInvoke[*elasticsearch.Client](i)
	return &EsSearchService{
		esClient: client,
	}, nil
}

func (es *EsSearchService) IndexProduct(ctx context.Context, event any) error {
	productEvent, ok := event.(*eventbus.AddProductEvent)
	if !ok {
		return errors.New("event is not AddProductEvent")
	}
	log.C(ctx).Infow("add event handler", "event", productEvent)

	//salePrice := productEvent.ProductInfo.ProductSalePrice.Mul(decimal.NewFromInt(100))
	var skuDocList = make([]SkuDoc, len(productEvent.ProductInfo.SkuList), len(productEvent.ProductInfo.SkuList))
	for idx, sku := range productEvent.ProductInfo.SkuList {
		skuDocList[idx] = SkuDoc{
			ID:          sku.ID,
			ShopPrice:   sku.ShopPrice,
			MarketPrice: sku.MarketPrice,
			Attributes:  sku.Attributes,
		}
	}
	productDoc := &ProductDoc{
		ID:          productEvent.ProductInfo.ID,
		Name:        productEvent.ProductInfo.Name,
		Description: productEvent.ProductInfo.Description,
		Skus:        skuDocList,
	}
	data, err := json.Marshal(productDoc)
	if err != nil {
		log.C(ctx).Errorw("json marshal error", "err", err)
		return fmt.Errorf("序列化ES文档失败: %v", err)
	}

	req := esapi.IndexRequest{
		Index:      ProductIndexName,
		DocumentID: strconv.FormatInt(productDoc.ID, 10),
		Body:       bytes.NewReader(data),
		Refresh:    "false",
	}
	res, err := req.Do(ctx, es.esClient)
	if err != nil || res.IsError() {
		log.C(ctx).Errorw("create index error", "err", err, "res", res)
		return fmt.Errorf("create index error: %v", err)
	}
	log.C(ctx).Infow("IndexProduct success", "productDoc", productDoc)
	return nil
}
